package com.bwda.dsrs.filecenter.ftpsdk.impl;

import com.jcraft.jsch.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @description:
 * @author: yangjun
 * @create: 2019-07-16 16:04
 */
public class SftpServiceImpl extends AbstractFtpService {
    private final Logger logger = LoggerFactory.getLogger(SftpServiceImpl.class);
    private ChannelSftp sftp = null;

    private SftpServiceImpl() {
    }

    public static SftpServiceImpl getInstance() {
        return new SftpServiceImpl();
    }

    @Override
    protected boolean connection() {
        boolean booResult = false;
        if (!this.inited) {
            return booResult;
        } else if (this.sftp != null) {
            return true;
        } else {
            this.sftp = new ChannelSftp();
            JSch jsch = new JSch();

            try {
                Session sshSession = jsch.getSession(this.username, this.ip, this.port);
                this.logger.info("Session创建");
                sshSession.setPassword(this.password);
                Properties sshConfig = new Properties();
                sshConfig.put("StrictHostKeyChecking", "no");
                sshSession.setConfig(sshConfig);
                if (this.timeout <= 0) {
                    sshSession.connect();
                } else {
                    sshSession.connect(this.timeout);
                }

                this.logger.info("SFTP Server:{},Port{},MSG:{}", new Object[]{this.ip, String.valueOf(this.port), "SFTP登陆成功"});
                Channel channel = sshSession.openChannel("sftp");
                if (this.timeout <= 0) {
                    channel.connect();
                } else {
                    channel.connect(this.timeout);
                }

                this.sftp = (ChannelSftp) channel;
                this.sftp.setFilenameEncoding("UTF-8");
                booResult = true;
            } catch (Exception var6) {
                this.logger.error("{}", var6.toString());
            }

            return booResult;
        }
    }

    @Override
    protected void disConnection() {
        if (this.sftp != null) {
            try {
                this.sftp.disconnect();
                if (this.sftp.getSession() != null) {
                    this.sftp.getSession().disconnect();
                }
            } catch (JSchException var5) {
                this.logger.error("{}", var5.toString());
            } finally {
                this.sftp = null;
            }
        }

    }

    @Override
    protected final boolean changeWorkingDirectorySub(String strWorkingDirectory) {
        boolean booResult = false;
        if (StringUtils.isNotBlank(strWorkingDirectory)) {
            this.logger.info("切换工作目录={}", strWorkingDirectory);

            try {
                if (this.sftp != null) {
                    try {
                        this.sftp.cd(strWorkingDirectory);
                        booResult = true;
                    } catch (SftpException var4) {
                        booResult = false;
                    }
                }
            } catch (Exception var5) {
                booResult = false;
                this.logger.error("{}", var5.toString());
            }
        }

        if (booResult) {
            this.workingDirectory = strWorkingDirectory;
        }

        this.logger.info("切换{},工作目录:{}", booResult ? "成功" : "失败", strWorkingDirectory);
        return booResult;
    }

    @Override
    protected final boolean uploadFileSub(String strLocalFile, String strRemotePath) {
        boolean booResult = false;
        FileInputStream inputStream = null;

        try {
            String fileName = this.getFileName(strLocalFile);
            String strRemoteFile = strRemotePath + fileName;
            inputStream = new FileInputStream(strLocalFile);
            if (this.sftp != null) {
                this.sftp.put(inputStream, strRemoteFile);
                inputStream.close();
                booResult = true;
                this.logger.info("工作目录:{},上传文件成功：{}", this.workingDirectory, strRemoteFile);
            }
        } catch (Exception var10) {
            this.logger.error("{}", var10.toString());
            booResult = false;
        } finally {
            inputStream = null;
        }

        return booResult;
    }

    protected final boolean uploadFile(String strRemoteFile, InputStream inputStreamLocal) {
        boolean booResult = false;

        try {
            if (this.sftp != null) {
                this.sftp.put(inputStreamLocal, strRemoteFile);
                inputStreamLocal.close();
                booResult = true;
                this.logger.info("工作目录:{},上传文件成功：{}", this.workingDirectory, strRemoteFile);
            }
        } catch (Exception var8) {
            this.logger.error("{}", var8.toString());
            booResult = false;
        } finally {
            inputStreamLocal = null;
        }

        return booResult;
    }

    @Override
    protected final boolean downloadFileSub(String strRemoteFile, String strLocalFile) {
        boolean booResult = false;
        File fileOut = new File(strLocalFile);
        FileOutputStream outputStream = null;

        try {
            outputStream = new FileOutputStream(fileOut);
            if (this.sftp != null && this.checkRemoteFileSub(strRemoteFile)) {
                this.sftp.get(strRemoteFile, outputStream);
                outputStream.close();
                booResult = true;
                this.logger.info("工作目录:{},下载文件成功：{}", this.workingDirectory, strRemoteFile);
            }
        } catch (Exception var10) {
            booResult = false;
            this.logger.error("{}", var10.toString());
        } finally {
            fileOut = null;
            outputStream = null;
        }

        return booResult;
    }

    protected final ByteArrayInputStream downloadFileAsStream(String strRemoteFile) {
        ByteArrayInputStream byteArrayInputStream = null;

        try {
            if (this.sftp != null && this.checkRemoteFileSub(strRemoteFile)) {
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                this.sftp.get(strRemoteFile, byteArrayOutputStream);
                byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
            }
        } catch (Exception var4) {
            this.logger.error("{}", var4.toString());
        }

        return byteArrayInputStream;
    }

    @Override
    protected final boolean checkRemoteFileSub(String strFileName) {
        boolean booResult = false;
        ChannelSftp.LsEntry lsEntry = null;

        try {
            Vector<ChannelSftp.LsEntry> vector = this.sftp.ls(strFileName);
            if (vector != null && !vector.isEmpty()) {
                lsEntry = (ChannelSftp.LsEntry) vector.get(0);
                booResult = true;
            }
        } catch (Exception var5) {
            this.logger.error("{}", var5.toString());
        }

        if (lsEntry == null) {
            this.logger.info("指定的FTP文件不存在，路径4：{},文件名：{}。", this.workingDirectory, strFileName);
        }

        return booResult;
    }

    protected final Vector<ChannelSftp.LsEntry> fileList() {
        Vector vector = null;

        try {
            vector = this.sftp.ls(this.sftp.pwd());
            if (vector != null && !vector.isEmpty()) {
                this.logger.info("ftpFileArray!=null");
                Iterator var3 = vector.iterator();

                while (var3.hasNext()) {
                    ChannelSftp.LsEntry lsEntry = (ChannelSftp.LsEntry) var3.next();
                    this.logger.info(lsEntry.getFilename());
                }
            } else {
                this.logger.info("目录：{},下面文件夹和文件数目为空", this.workingDirectory);
            }
        } catch (Exception var4) {
            this.logger.error("{}", var4.toString());
            vector = null;
        }

        return vector;
    }

    @Override
    protected final List<String> getFileListSub(String strRemotePath) {
        List<String> ftpFileList = new ArrayList();
        Vector vector = null;

        try {
            if (this.changeWorkingDirectorySub(strRemotePath)) {
                vector = this.sftp.ls(strRemotePath);
                if (vector != null && !vector.isEmpty()) {
                    this.logger.info("ftpFileArray!=null");
                    Iterator var5 = vector.iterator();

                    while (var5.hasNext()) {
                        ChannelSftp.LsEntry lsEntry = (ChannelSftp.LsEntry) var5.next();
                        this.logger.info(lsEntry.getFilename());
                        ftpFileList.add(lsEntry.getFilename());
                    }
                } else {
                    this.logger.info("目录：{},下面文件夹和文件数目为空", this.workingDirectory);
                }
            }
        } catch (Exception var6) {
            this.logger.error("{}", var6.toString());
            vector = null;
        }

        return ftpFileList;
    }

    @Override
    protected final boolean deleteFileSub(String strRemoteFileName) {
        boolean booResult = false;

        try {
            if (this.sftp != null) {
                this.sftp.rm(strRemoteFileName);
                booResult = true;
                this.logger.info("工作目录:{},删除文件成功：{}", this.workingDirectory, strRemoteFileName);
            }
        } catch (Exception var4) {
            booResult = false;
            this.logger.error("{}", var4.toString());
        }

        return booResult;
    }

    @Override
    protected final boolean renameSub(String strRemoteOldName, String strRemoteNewName) {
        boolean booResult = false;

        try {
            if (this.sftp != null) {
                this.sftp.rename(strRemoteOldName, strRemoteNewName);
                booResult = true;
                this.logger.info("工作目录:{},文件重命名成功：{}", this.workingDirectory, strRemoteNewName);
            }
        } catch (Exception var5) {
            booResult = false;
            this.logger.error("{}", var5.toString());
        }

        return booResult;
    }

    @Override
    protected final boolean createDirectorySub(String strWorkingDirectory) {
        boolean booResult = false;
        if (StringUtils.isNotBlank(strWorkingDirectory)) {
            try {
                try {
                    this.sftp.cd(strWorkingDirectory);
                    booResult = true;
                } catch (Exception var11) {
                    String[] strArrayDirs = StringUtils.split(strWorkingDirectory, "/");
                    this.sftp.cd("/");
                    String[] var8 = strArrayDirs;
                    int var7 = strArrayDirs.length;

                    for (int var6 = 0; var6 < var7; ++var6) {
                        String strDir = var8[var6];

                        try {
                            this.sftp.ls(strDir);
                        } catch (Exception var10) {
                            this.sftp.mkdir(strDir);
                        }

                        this.sftp.cd(strDir);
                    }

                    this.sftp.cd(strWorkingDirectory);
                    booResult = true;
                }
            } catch (Exception var12) {
                booResult = false;
            }
        }

        return booResult;
    }

    @Override
    protected final boolean removeDirectorySub(String strWorkingDirectory) {
        boolean booResult = true;

        try {
            booResult = this.removeAll(strWorkingDirectory);
            this.logger.info("工作目录:{},删除目录成功：{}", this.workingDirectory, strWorkingDirectory);
        } catch (Exception var4) {
            booResult = false;
            this.logger.error("{}", var4.toString());
        }

        return booResult;
    }

    private boolean removeAll(String folderDir) {
        try {
            this.sftp.cd(folderDir);
            Vector<ChannelSftp.LsEntry> vector = this.fileList();
            if (vector != null && !vector.isEmpty()) {
                Iterator var4 = vector.iterator();

                while (var4.hasNext()) {
                    ChannelSftp.LsEntry lsEntry = (ChannelSftp.LsEntry) var4.next();
                    if (lsEntry.getAttrs().isDir() && !StringUtils.equals(".", lsEntry.getFilename()) && !StringUtils.equals("..", lsEntry.getFilename())) {
                        this.removeAll(folderDir + "/" + lsEntry.getFilename());
                    }

                    if (!lsEntry.getAttrs().isDir()) {
                        this.sftp.rm(folderDir + "/" + lsEntry.getFilename());
                    }
                }
            }

            this.sftp.rmdir(folderDir);
            return true;
        } catch (Exception var5) {
            this.logger.error("{}", var5.toString());
            return false;
        }
    }

    @Override
    protected final boolean copyFileSub(String strRemoteSourceFile, String strRemoteTargetFile) {
        boolean booResult = false;

        try {
            if (this.sftp != null) {
                String strDir = StringUtils.substringBeforeLast(strRemoteSourceFile, "/");
                if (this.checkRemoteFileSub(strRemoteSourceFile)) {
                    InputStream in = this.downloadFileAsStream(strRemoteSourceFile);
                    strDir = StringUtils.substringBeforeLast(strRemoteTargetFile, "/");
                    String strSuffix = StringUtils.substringAfterLast(strRemoteTargetFile, ".");
                    if (this.checkRemoteFileSub(strRemoteTargetFile)) {
                        String strSubNewFileName = (new SimpleDateFormat("_MMddHHmmss")).format(new Date());
                        strRemoteTargetFile = StringUtils.substringBeforeLast(strRemoteTargetFile, ".").replaceAll("_\\d{10,}", "") + strSubNewFileName;
                        if (StringUtils.isNotBlank(strSuffix)) {
                            strRemoteTargetFile = strRemoteTargetFile + "." + strSuffix;
                        }
                    }

                    strDir = StringUtils.substringBeforeLast(strRemoteTargetFile, "/");
                    if (StringUtils.isNotBlank(strDir) && !this.changeWorkingDirectorySub(strDir)) {
                        this.createDirectorySub(strDir);
                    }

                    booResult = this.uploadFile(strRemoteTargetFile, in);
                } else {
                    this.logger.error("源文件不存在:{}", strRemoteSourceFile);
                }
            }
        } catch (Exception var8) {
            booResult = false;
            this.logger.error("{}", var8.toString());
        }

        return booResult;
    }
}
